﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using NetCoreServer;

namespace DyData
{
    internal class HttpServer
    { 
    }

    class CommonCache
    {

        public static CommonCache GetInstance()
        {
            if (_instance == null)
                _instance = new CommonCache();
            return _instance;
        }

        public string GetAllCache()
        {
            var result = new StringBuilder();
            result.Append("[\n");
            foreach (var item in _cache)
            {
                result.Append("  {\n");
                result.AppendFormat($"    \"key\": \"{item.Key}\",\n");
                result.AppendFormat($"    \"value\": \"{item.Value}\",\n");
                result.Append("  },\n");
            }
            result.Append("]\n");
            return result.ToString();
        }

        public bool GetCacheValue(string key, out string value)
        {
            return _cache.TryGetValue(key, out value);
        }

        public void PutCacheValue(string key, string value)
        {
            _cache[key] = value;
        }

        public bool DeleteCacheValue(string key, out string value)
        {
            return _cache.TryRemove(key, out value);
        }

        private readonly ConcurrentDictionary<string, string> _cache = new ConcurrentDictionary<string, string>();
        private static CommonCache _instance = null!;
    }

    class HttpCacheSession : HttpSession
    {
        public HttpCacheSession(NetCoreServer.HttpServer server) : base(server) { }
        public Logger _logger;
        protected override void OnReceivedRequest(HttpRequest request)
        {
            // Show HTTP request content
            _logger.LogInfo(request.ToString());

            switch (request.Method)
            {
                case "HEAD": SendResponseAsync(Response.MakeHeadResponse());
                break;
                case "GET": 
                {
                        /*
                          string responseString = @"
                            <html>
                                <body>
                                    <form action='/' method='post'>
                                        <label for='input1'>输入1:</label>
                                        <input type='text' id='input1' name='input1'><br><br>
                                        <label for='input2'>输入2:</label>
                                        <input type='text' id='input2' name='input2'><br><br>
                                        <input type='submit' value='提交'>
                                    </form>
                                </body>
                            </html>";

                            SendResponseAsync(Response.MakeGetResponse(responseString, "text/html; charset=UTF-8"));

                         string responseString = @"
                            <html>
                                <body>
                                    <h1>表单提交成功!</h1>
                                    <p>您的数据已保存。</p>
                                </body>
                            </html>";
    
                            SendResponseAsync(Response.MakeGetResponse(responseString, "text/html; charset=UTF-8"));
                         */

                        string key = request.Url;

                    _logger.LogWarning("key: "+key);

                    // Decode the key value
                    key = Uri.UnescapeDataString(key);
                    key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
                    key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);

                    if (string.IsNullOrEmpty(key))
                    {
                        // Response with all cache values
                        SendResponseAsync(Response.MakeGetResponse(CommonCache.GetInstance().GetAllCache(), "application/json; charset=UTF-8"));
                    }
                 }
                 break;
                case "POST" or "PUT":  
                  {
                        string key = request.Url;
                        string value = request.Body;

                        // Decode the key value
                        key = Uri.UnescapeDataString(key);
                        key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
                        key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);

                        // Put the cache value
                        CommonCache.GetInstance().PutCacheValue(key, value);

                        // Response with the cache value
                        SendResponseAsync(Response.MakeOkResponse());

                        /*
                         // 解析表单数据
                            var body = request.Body;
                            var parameters = body.Split('&');
                            var input1 = WebUtility.UrlDecode(parameters[0].Split('=')[1]);
                            var input2 = WebUtility.UrlDecode(parameters[1].Split('=')[1]);
    
                            // 处理表单数据...
    
                            // 准备重定向响应
                            Response.Clear();
                            Response.SetBegin(302); // 302 Found - 临时重定向
                            Response.SetHeader("Location", "/success");
                            Response.SetBody();
    
                            SendResponseAsync(Response);
                         */
                    }
                    break;
                case "DELETE":
                    {
                        string key = request.Url;

                        // Decode the key value
                        key = Uri.UnescapeDataString(key);
                        key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
                        key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);

                        // Delete the cache value
                        if (CommonCache.GetInstance().DeleteCacheValue(key, out var value))
                        {
                            // Response with the cache value
                            SendResponseAsync(Response.MakeGetResponse(value));
                        }
                        else
                            SendResponseAsync(Response.MakeErrorResponse(404, "Deleted cache value was not found for the key: " + key));
                    }
                    break;
                case "OPTIONS":  SendResponseAsync(Response.MakeOptionsResponse());
                    break;
                case "TRACE":  SendResponseAsync(Response.MakeTraceResponse(request.Cache.Data));
                    break;
                default:  SendResponseAsync(Response.MakeErrorResponse("Unsupported HTTP method: " + request.Method));
                    break;
            }

            /*
            // Process HTTP request methods
            if (request.Method == "HEAD")
                SendResponseAsync(Response.MakeHeadResponse());
            else if (request.Method == "GET")
            {
                string key = request.Url;


                _logger.LogInfo(key);

                // Decode the key value
                key = Uri.UnescapeDataString(key);
                key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
                key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);

                if (string.IsNullOrEmpty(key))
                {
                    // Response with all cache values
                    SendResponseAsync(Response.MakeGetResponse(CommonCache.GetInstance().GetAllCache(), "application/json; charset=UTF-8"));
                }
                // Get the cache value by the given key
                else if (CommonCache.GetInstance().GetCacheValue(key, out var value))
                {
                    // Response with the cache value
                    SendResponseAsync(Response.MakeGetResponse(value));
                }
                else
                    SendResponseAsync(Response.MakeErrorResponse(404, "Required cache value was not found for the key: " + key));
            }
            else if ((request.Method == "POST") || (request.Method == "PUT"))
            {
                string key = request.Url;
                string value = request.Body;

                // Decode the key value
                key = Uri.UnescapeDataString(key);
                key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
                key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);

                // Put the cache value
                CommonCache.GetInstance().PutCacheValue(key, value);

                // Response with the cache value
                SendResponseAsync(Response.MakeOkResponse());
            }
            else if (request.Method == "DELETE")
            {
                string key = request.Url;

                // Decode the key value
                key = Uri.UnescapeDataString(key);
                key = key.Replace("/api/cache", "", StringComparison.InvariantCultureIgnoreCase);
                key = key.Replace("?key=", "", StringComparison.InvariantCultureIgnoreCase);

                // Delete the cache value
                if (CommonCache.GetInstance().DeleteCacheValue(key, out var value))
                {
                    // Response with the cache value
                    SendResponseAsync(Response.MakeGetResponse(value));
                }
                else
                    SendResponseAsync(Response.MakeErrorResponse(404, "Deleted cache value was not found for the key: " + key));
            }
            else if (request.Method == "OPTIONS")
                SendResponseAsync(Response.MakeOptionsResponse());
            else if (request.Method == "TRACE")
                SendResponseAsync(Response.MakeTraceResponse(request.Cache.Data));
            else
                SendResponseAsync(Response.MakeErrorResponse("Unsupported HTTP method: " + request.Method));
         */
        }


        protected override void OnReceivedRequestError(HttpRequest request, string error)
        {
            _logger.LogInfo($"Request error: {error}");
        }

        protected override void OnError(SocketError error)
        {
            _logger.LogInfo($"HTTP session caught an error: {error}");
        }
    }

    class HttpCacheServer : NetCoreServer.HttpServer
    {
        public HttpCacheServer(IPAddress address, int port) : base(address, port) { }

        public Logger hcslogger;

        protected override TcpSession CreateSession() {
             var hcs = new HttpCacheSession(this);
            hcs._logger = hcslogger;
            return hcs;
        }

        protected override void OnError(SocketError error)
        {
            hcslogger.LogInfo($"HTTP session caught an error: {error}");
        }
    }

}
